package com.kanq.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kanq.documentLoader.Loader;
import com.kanq.factory.ChatServiceFactory;
import com.kanq.handler.ResponseGeneratorHandler;
import com.kanq.mapper.KanqAiFileTypeMapper;
import com.kanq.mapper.LLMMapper;
import com.kanq.pojo.entity.KanqAiFileType;
import com.kanq.pojo.entity.Llm;
import com.kanq.pojo.request.ChatRequest;
import com.kanq.service.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.Disposable;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;


@Service
@Slf4j
public class LLMServiceImpl extends ServiceImpl<LLMMapper, Llm> implements LLMService {

    // 静态文件类型列表，避免重复初始化
    private static List<KanqAiFileType> types = null;
    @Resource
    private ChatClient defaultClient;
    @Resource
    private KanqAiFileTypeMapper kanqAiFileTypeMapper;
    @Resource
    private KanqAiPromptService kanqAiPromptService;
    @Resource
    private KanqAiFileService kanqAiFileService;
    @Resource
    private KanqAiFileChunkService kanqAiFileChunkService;
    @Resource
    private Loader loader;
    @Resource
    private ChatServiceFactory chatServiceFactory;
    private String prompt = null;


    @Override
    @Transactional
    public int readFile(MultipartFile file) {
        // 初始化或获取文件类型列表
        if (types == null) {
            types = kanqAiFileTypeMapper.selectList(Wrappers.<KanqAiFileType>lambdaQuery().eq(KanqAiFileType::getIsDeleted, 0));
        }

        assert types != null;
        if (prompt == null) {
            prompt = kanqAiPromptService.getByName("file_classify");
        }

        assert prompt != null;

        // 根据文件名进行分类
        String filetypes = types.stream().map(KanqAiFileType::getName).reduce("", (a, b) -> a + "\n" + b);
        log.info("filetypes: {}", filetypes);
        // 构造提示信息，包含文件类型和文件名
        String promptWithFile = prompt.replace("{filetypes}", filetypes).replace("{filename}", file.getOriginalFilename());
        log.info("promptWithFile: {}", promptWithFile);
        // 与用户输入进行交互，获取文件分类结果
        String result = chat(promptWithFile).replaceAll("\n", "");
        log.info("result: {}", result);
        // 根据结果查找文件类型ID
        long typeId;
        try {
            typeId = types.stream().filter(t -> t.getName().equals(result)).findFirst().orElseThrow().getId();
        } catch (Exception e) {
            return -2;
        }
        // 创建新文件
        var fileId = kanqAiFileService.newFile(file.getOriginalFilename(), typeId);
        // 提取文件内容并插入数据库
        try {
            var sections = loader.load(file.getOriginalFilename(), file.getInputStream());
            if (sections == null) {
                return -1;
            }

            log.info("sections: {}", sections);
            // 将文件分块插入知识库
            if (!kanqAiFileChunkService.saveFileChunk(fileId, file.getOriginalFilename(), sections.getSections())) {
                return -1;
            }
            // 插入向量数据库

        } catch (IOException e) {
            return -1;
        }
        // 处理失败，返回错误码
        return -1;
    }

    @Override
    public String chat(String prompt) {
        return defaultClient.prompt().user(prompt).call().content();
    }

    @Override
    public SseEmitter sseChat(ChatRequest chatRequest, ConcurrentHashMap<String, SseEmitter> taskEmitterMap) {
        SseEmitter sseEmitter = new SseEmitter(0L);

        // 根据模型分类调用不同的处理逻辑
        IChatService chatService = chatServiceFactory.getChatService("chat");
        return chatService.chat(chatRequest, sseEmitter, taskEmitterMap);
    }

    @Override
    public void stopChat(String taskId, ConcurrentHashMap<String, SseEmitter> taskEmitterMap) {
        SseEmitter emitter = taskEmitterMap.get(taskId);
        if (emitter != null) {
            emitter.complete();
            taskEmitterMap.remove(taskId);

            // 获取并停止对应的Disposable
            Disposable disposable = ResponseGeneratorHandler.getDisposableByTaskId(taskId);
            if (disposable != null && !disposable.isDisposed()) {
                disposable.dispose();
            }
        }
    }


}
